#!/usr/bin/env python
# encoding: utf-8

"""
@time: 2016/11/23 下午5:41
"""
# 用来存放常用的condition

from mathsolver.functions.base import *
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.budengshi.jiebudengshi import JieBuDengShi
from itertools import repeat
from sympy import symbols, solveset


# 已知a,b为正实数
class ZhengShiShu001(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseVariables):
            vs = args[0].value
        elif isinstance(args[0], BaseVariable):
            vs = [args[0].value]
        vs_print = ', '.join(map(lambda tmp_v: '%s > 0' % str(tmp_v), vs))
        for v in vs:
            self.output.append(BaseSymbolValue({v: solveset(sympify(str(v)) > 0, domain=S.Reals)}))
        self.steps.append(['由题意可知 ' + vs_print, ''])
        return self


# 若a,b∈R_{+}
class ZhengShiShu002(BaseFunction):
    def solver(self, *args):
        if not isinstance(args[0], BaseBelong):
            raise Exception('Type Match Error')
        vs = args[0].var
        if isinstance(args[0].interval, str) and args[0].interval.find('R_{+}') >= 0:
            vs_print = ', '.join(map(lambda tmp_v: '%s > 0' % str(tmp_v), vs))
            for v in vs:
                self.output.append(BaseSymbolValue({v: solveset(sympify(str(v)) > 0, domain=S.Reals)}))
            self.steps.append(['由题意可知 ' + vs_print, ''])
        elif isinstance(args[0].interval, Interval):
            self.output.append(BaseSymbolValue({args[0].var: args[0].interval}))
        return self


class ZhengShiShu003(BaseFunction):
    def solver(self, *args):
        if not isinstance(args[0], BaseMultiple):
            raise Exception('Type Match Error')
        variables = args[0].sympify()
        for v in variables:
            self.output.append(BaseSymbolValue({v: solveset(sympify(str(v)) > 0, domain=S.Reals)}))
        return self


# 正实数条件
class ZhengShiShuCondition(BaseFunction):
    CLS = [ZhengShiShu001, ZhengShiShu002, ZhengShiShu003]

    def solver(self, *args):
        r = None
        for cl in ZhengShiShuCondition.CLS:
            try:
                r = cl(verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r


# 分段函数的条件
# 664478 已知函数f(x)=\\left\\{\\begin{array}{c}x+2,x≤0\\\\-x+2,x>0\\end{array}\\right.,求不等式f(x)≤x^{2}的解集.
class HanShu001(BaseFunction):
    def solver(self, *args):
        self.label.add('分段函数')
        self.output.append(BaseSymbolValue({'f(x)': args[0]}))
        return self


class HanShu002(BaseFunction):
    def solver(self, *args):
        return self


# 所有函数的条件
class HanShu(BaseFunction):
    CLS = [HanShu001, ]

    def solver(self, *args):
        r = None
        for cl in HanShu.CLS:
            try:
                r = cl(verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r


# 设函数f(x)=\\left\\{\\begin{array}{c}{x}^{2}(x≤0)\\\\\\sqrt{x}(x>0)\\end{array}\\right.,若f(a)>1,则a的取值范围是()
class BuDengShiBiaoDaShi001(BaseFunction):
    def solver(self, *args):
        ineq_expr = args[0].value
        func = args[1]
        ineq_op = re.findall('>=|<=|>|<', ineq_expr)[0]
        l_expr, r_expr = ineq_expr.split(ineq_op)
        # ineq_f = l_expr - r_expr
        # self.output.append(BaseSymbolValue({'f': func}))
        # self.output.append(BaseIneq([l_expr, ineq_op, r_expr]))
        # if len(ineq_f.free_symbols) == 1:
        #     return JieBuDengShi(verbose=True).solver(func, BaseIneq([l_expr, ineq_op, r_expr]))
        # else:
        #     return
        return JieBuDengShi(verbose=True).solver(func, BaseIneq([l_expr, ineq_op, r_expr]))


# 不等式表达式 输出为BaseIneq
# 会首先搜选条件
# # 该条件是把不等式函数表达式，放入到内存中。然后解不等式的时候，从内存中搜寻出不等式表达式.在输出一个不等式，然后会匹配到解不等式
class BuDengShiBiaoDaShi(BaseFunction):
    CLS = [BuDengShiBiaoDaShi001, ]

    def solver(self, *args):
        tmp_args = [arg for arg in args]
        if 'f' in self.known:
            tmp_args.append(self.known['f'])
        r = None
        for cl in BuDengShiBiaoDaShi.CLS:
            try:
                r = cl(verbose=True).solver(*tmp_args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r


# 若不等式组\\{\\begin{array}{c}x+y-2≤ 0,\\\\ x+2y-2≥ 0,\\\\ x-y+2m≥ 0\\end{array}表示的平面区域为三角形,
# 其面积等于\\dfrac {4}{3},则m的值为 ()
# style1 Input paramer1:ineqs(不等式组);  Ouput: 面积的值
# style2 Input paramer2:ineqs(不等式组); paramer2:面积值  Ouput: 参数的值
class PingMianQuYuMianJi(BaseFunction):
    def solver(self, *args):
        self.label.add('线性规划可行域面积')
        ineqs = args[0]
        ineqs = co.simp_ineqs(ineqs)
        inter_points = list(map(lambda _: list(zip(*_[1]))[1], co.satisfied_ineqs_intersections(ineqs)))
        points_print = ''
        for _p in inter_points:
            points_print += ' ' + co.point_print(_p)
        self.steps.append(['由约束条件可知交点为:', points_print])
        from mathsolver.functions.yuanzhui.graph import ComputeArea
        p1, p2, p3 = symbols('p1, p2, p3')
        pv1, pv2, pv3 = inter_points
        area_expr = ComputeArea(known={p1: BasePoint(list(pv1)), p2: BasePoint(list(pv2)), p3: BasePoint(list(pv3))}).solver(BasePointNames(value=[p1, p2, p3])).output[0].sympify()
        area_expr = sympify(str(area_expr))
        if not area_expr.free_symbols:  # 如果可以直接求出面积那么直接输出
            self.steps.append(['求的面积为:', new_latex(area_expr)])
            self.output.append(BaseNumber(area_expr))
            return self
        else:
            area_value = args[1].sympify()
            param_symb = list(area_expr.free_symbols)[0]
            _eq = [area_expr, area_value]
            self.steps.append(['可以得出:', BaseEq(_eq).printing()])
            param_values = co.isolve_eq2(BaseEq(_eq))
            self.steps.append(['得出:', new_latex(FiniteSet(*param_values))])
            last_param_values = []
            for pv in param_values:
                ineqs2 = BaseIneqs(list(map(lambda _: [_[0].subs(param_symb, pv), _[1], _[2].subs(param_symb, pv)], ineqs.sympify())))
                inter_points2 = co.satisfied_ineqs_intersections(ineqs2)
                if len(inter_points2) == len(inter_points):
                    last_param_values.append(pv)
            self.steps.append(['验证求得:', new_latex(param_symb) + ' 值为:' + new_latex(FiniteSet(*last_param_values))])
            self.output.append(BaseSymbolValue({param_symb: last_param_values}))
            return self


# (不含参的)多条直线所围成的区域条件转换为不等式表示的
# style1 Input paramer1: BaseEqs
# style1 Input paramer1: baseq; paramer2:BaseEq
class QuYuZhuanHuanCondition(BaseFunction):
    def solver(self, *args):
        self.label.add('线性规划可行域表示')
        eqs = []
        for arg in args:
            if isinstance(arg, BaseEqs):
                eqs.extend(arg.sympify())
            elif isinstance(arg, BaseEq):
                eqs.append(arg.sympify())
        exprs = []
        for eq in eqs:
            l, r = eq
            f = l - r
            exprs.extend(co.remove_param_abs_expr(f))
        size = len(exprs)
        ops = list(repeat(['>=', '<='], size))
        op_combins = co.combin_iters(*ops)
        last_ineqs = []
        for ops in op_combins:
            _ineqs = map(lambda _: [_[0], _[1], 0], zip(exprs, ops))
            inters = co.satisfied_ineqs_intersections(BaseIneqs(_ineqs))
            if len(inters) > 2:
                last_ineqs = _ineqs
                break
        self.steps.append(['由题意可知平面区域可表示为:', ''])
        self.steps.append([BaseIneqs(last_ineqs).printing(), ''])
        self.output.append(BaseIneqs(last_ineqs))
        return self


if __name__ == '__main__':
    # _solve = PingMianQuYuMianJi().solver(
    #     BaseIneqs([['x + y - 2', '<=', '0'], ['x+2*y - 2', '>=', '0'], ['x - y + 2*m', '>=', '0']]),
    #     BasePoly('4/3'))
    # for s1, s2 in _solve.steps:
    #     print s1, s2
    _solve = QuYuZhuanHuanCondition().solver(BaseEq(['y', 'Abs(x - 1)']), BaseEq(['y', '2']))
